`include "ysyx_23060189_isa.svh"
`include "ysyx_23060189_cpu.svh"
`include "ysyx_23060189_decode.svh"

module ysyx_23060189_Decoder (
  input  wire [`ysyx_23060189_DataBus]     inst,
  output wire [`ysyx_23060189_PcSelBus]    PC_sel,
  output wire [`ysyx_23060189_ImmSelBus]   Imm_sel,
  output wire [`ysyx_23060189_AluOpBus]    Alu_op,
  output wire [`ysyx_23060189_StTypeBus]   st_type,
  output wire [`ysyx_23060189_LdTypeBus]   ld_type,
  output wire [`ysyx_23060189_BrTypeBus]   br_type,
  output wire [`ysyx_23060189_AluSelBus]   A_sel,
  output wire [`ysyx_23060189_AluSelBus]   B_sel,
  output wire [`ysyx_23060189_CsrTypeBus]  csr_cmd,
  output wire [`ysyx_23060189_WbSelBus]    wb_sel,
  output wb_en
);

  wire [`ysyx_23060189_IsaOpBus]     isa_op     = inst[`ysyx_23060189_IsaOpOps];
  wire [`ysyx_23060189_IsaFunct3Bus] isa_funct3 = inst[`ysyx_23060189_IsaFunct3Ops];
  wire [`ysyx_23060189_IsaFunct7Bus] isa_funct7 = inst[`ysyx_23060189_IsaFunct7Ops];
  // 通过opcode寻找指令
  // flag0为1: 找到，0为：未找到，继续寻找
  wire flag0;
  wire [`ysyx_23060189_CtrlSignalBus] ctrlSignal0;
  // 通过opcode+funct3寻找指令
  // flag1为1: 找到，0为：未找到，继续寻找
  wire flag1;
  wire [`ysyx_23060189_CtrlSignalBus] ctrlSignal1;
  // 通过opcode+funct3+funct7寻找指令
  // flag2为1: 找到，0为：未找到，继续寻找
  wire flag2;
  wire [`ysyx_23060189_CtrlSignalBus] ctrlSignal2;
  // 通过整个指令寻找
  wire flag3;
  wire [`ysyx_23060189_CtrlSignalBus] ctrlSignal3;
  // 最终的译码信号 
  wire [`ysyx_23060189_CtrlSignalBus] ctrlSignal;

  // 通过opcode寻找指令
  MuxKeyWithDefault #(3, 7, `ysyx_23060189_CTRL_SIGNAL_LENGTH + 1) Mux0 ({flag0, ctrlSignal0}, isa_op, {1'b0, `ysyx_23060189_DEFAULT_DECODE}, {
    `ysyx_23060189_ISA_LUI,   {1'b1, `ysyx_23060189_LUI_DECODE},
    `ysyx_23060189_ISA_AUIPC, {1'b1, `ysyx_23060189_AUIPC_DECODE},
    `ysyx_23060189_ISA_JAL,   {1'b1, `ysyx_23060189_JAL_DECODE}
  });

  // 通过opcode+funct3寻找指令
  MuxKeyWithDefault #(23, 10, `ysyx_23060189_CTRL_SIGNAL_LENGTH + 1) Mux1 ({flag1, ctrlSignal1}, {isa_funct3, isa_op}, {1'b0, `ysyx_23060189_DEFAULT_DECODE}, {
    `ysyx_23060189_ISA_JALR,  {1'b1, `ysyx_23060189_JALR_DECODE},
    `ysyx_23060189_ISA_BEQ,   {1'b1, `ysyx_23060189_BEQ_DECODE},
    `ysyx_23060189_ISA_BNE,   {1'b1, `ysyx_23060189_BNE_DECODE},
    `ysyx_23060189_ISA_BLT,   {1'b1, `ysyx_23060189_BLT_DECODE},
    `ysyx_23060189_ISA_BGE,   {1'b1, `ysyx_23060189_BGE_DECODE},
    `ysyx_23060189_ISA_BLTU,  {1'b1, `ysyx_23060189_BLTU_DECODE},
    `ysyx_23060189_ISA_BGEU,  {1'b1, `ysyx_23060189_BGEU_DECODE},
    `ysyx_23060189_ISA_LB,    {1'b1, `ysyx_23060189_LB_DECODE},
    `ysyx_23060189_ISA_LH,    {1'b1, `ysyx_23060189_LH_DECODE},
    `ysyx_23060189_ISA_LW,    {1'b1, `ysyx_23060189_LW_DECODE},
    `ysyx_23060189_ISA_LBU,   {1'b1, `ysyx_23060189_LBU_DECODE},
    `ysyx_23060189_ISA_LHU,   {1'b1, `ysyx_23060189_LHU_DECODE},
    `ysyx_23060189_ISA_SB,    {1'b1, `ysyx_23060189_SB_DECODE},
    `ysyx_23060189_ISA_SH,    {1'b1, `ysyx_23060189_SH_DECODE},
    `ysyx_23060189_ISA_SW,    {1'b1, `ysyx_23060189_SW_DECODE},
    `ysyx_23060189_ISA_ADDI,  {1'b1, `ysyx_23060189_ADDI_DECODE},
    `ysyx_23060189_ISA_SLTI,  {1'b1, `ysyx_23060189_SLTI_DECODE},
    `ysyx_23060189_ISA_SLTIU, {1'b1, `ysyx_23060189_SLTIU_DECODE},
    `ysyx_23060189_ISA_XORI,  {1'b1, `ysyx_23060189_XORI_DECODE},
    `ysyx_23060189_ISA_ORI,   {1'b1, `ysyx_23060189_ORI_DECODE},
    `ysyx_23060189_ISA_ANDI,  {1'b1, `ysyx_23060189_ANDI_DECODE},
    `ysyx_23060189_ISA_CSRRW, {1'b1, `ysyx_23060189_CSRRW_DECODE},
    `ysyx_23060189_ISA_CSRRS, {1'b1, `ysyx_23060189_CSRRS_DECODE}
  });

  // 通过opcode+funct3+funct7寻找指令
  MuxKeyWithDefault #(13, 17, `ysyx_23060189_CTRL_SIGNAL_LENGTH + 1) Mux2 ({flag2, ctrlSignal2}, {isa_funct7, isa_funct3, isa_op}, {1'b0, `ysyx_23060189_DEFAULT_DECODE}, {
    `ysyx_23060189_ISA_SLLI,  {1'b1, `ysyx_23060189_SLLI_DECODE},
    `ysyx_23060189_ISA_SRLI,  {1'b1, `ysyx_23060189_SRLI_DECODE},
    `ysyx_23060189_ISA_SRAI,  {1'b1, `ysyx_23060189_SRAI_DECODE},
    `ysyx_23060189_ISA_ADD,   {1'b1, `ysyx_23060189_ADD_DECODE},
    `ysyx_23060189_ISA_SUB,   {1'b1, `ysyx_23060189_SUB_DECODE},
    `ysyx_23060189_ISA_SLL,   {1'b1, `ysyx_23060189_SLL_DECODE},
    `ysyx_23060189_ISA_SLT,   {1'b1, `ysyx_23060189_SLT_DECODE},
    `ysyx_23060189_ISA_SLTU,  {1'b1, `ysyx_23060189_SLTU_DECODE},
    `ysyx_23060189_ISA_XOR,   {1'b1, `ysyx_23060189_XOR_DECODE},
    `ysyx_23060189_ISA_SRL,   {1'b1, `ysyx_23060189_SRL_DECODE},
    `ysyx_23060189_ISA_SRA,   {1'b1, `ysyx_23060189_SRA_DECODE},
    `ysyx_23060189_ISA_OR,    {1'b1, `ysyx_23060189_OR_DECODE},
    `ysyx_23060189_ISA_AND,   {1'b1, `ysyx_23060189_AND_DECODE}
   });

  // 通过整个指令寻找
  MuxKeyWithDefault #(3, 32, `ysyx_23060189_CTRL_SIGNAL_LENGTH + 1) Mux3 ({flag3, ctrlSignal3}, inst, {1'b0, `ysyx_23060189_DEFAULT_DECODE}, {
    `ysyx_23060189_ISA_EBREAK, {1'b1, `ysyx_23060189_DEFAULT_DECODE},
    `ysyx_23060189_ISA_ECALL,  {1'b1, `ysyx_23060189_ECALL_DECODE},
    `ysyx_23060189_ISA_MRET,   {1'b1, `ysyx_23060189_MRET_DECODE}
  });

  MuxKey #(5, 4, `ysyx_23060189_CTRL_SIGNAL_LENGTH) Mux4 (ctrlSignal, {flag3, flag2, flag1, flag0}, {
    4'b0001, ctrlSignal0,
    4'b0010, ctrlSignal1,
    4'b0100, ctrlSignal2,
    4'b0110, ctrlSignal2,
    4'b1000, ctrlSignal3
  });



  assign PC_sel  = ctrlSignal[26:25];
  assign Imm_sel = ctrlSignal[24:22];
  assign Alu_op  = ctrlSignal[21:18];
  assign st_type = ctrlSignal[17:16];
  assign ld_type = ctrlSignal[15:13];
  assign br_type = ctrlSignal[12:10];
  assign A_sel   = ctrlSignal[9:8];
  assign B_sel   = ctrlSignal[7:6];
  assign wb_sel  = ctrlSignal[5:4];
  assign csr_cmd = ctrlSignal[3:1];
  assign wb_en   = ctrlSignal[0:0];

  export "DPI-C" function IsEbreak;
  export "DPI-C" function Flag;

  function void IsEbreak(output int ebreak);
    if (inst == `ysyx_23060189_ISA_EBREAK) begin
      ebreak = 1;
    end else begin
      ebreak = 0;
    end
  endfunction

  function void Flag(output byte flag);
    flag = {4'b0, flag3, flag2, flag1, flag0};
  endfunction

endmodule
